#include "RBTransformComponent.h"

#include "RBMain/RBEntity.h"

RB_IMPLEMENT_COMPONENT(RBTransformComponent);

std::vector<RBTransform> RBTransformComponent::WorldXForms;
std::vector<RBTransform> RBTransformComponent::LocalXForms;
std::vector<RBTransformComponentHandle> RBTransformComponent::Parents;

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
RBTransformComponent::RBTransformComponent( RBEntityHandle entityHandle )
: RBTComponent( entityHandle )
, m_handle((uint16)WorldXForms.size())
, m_children(NULL)
{
    WorldXForms.push_back(RBTransform());
    LocalXForms.push_back(RBTransform());
    Parents.push_back(0xFFFF);
}

RBTransformComponent::~RBTransformComponent()
{
    stb_arr_free(m_children);
}


RBTransformComponent::RBTransformComponent( const RBTransformComponent& rhs )
: RBTComponent(rhs.GetEntityHandle())
, m_children(NULL)
{
    *this = rhs;
}


RBTransformComponent& RBTransformComponent::operator=( const RBTransformComponent& rhs )
{
    m_entity = rhs.GetEntityHandle();
    m_handle = rhs.m_handle;
    m_children = (RBTransformComponentHandle*)stb_arr_copy(rhs.m_children);
    return *this;
}


/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBTransformComponent::SetParent( RBTransformComponentHandle handle )
{
    Parents[m_handle] = handle;
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBTransformComponent::AddChild( RBTransformComponentHandle handle )
{
    RBTransformComponent& child = Get(handle);
    child.SetParent(m_handle);
    stb_arr_push(m_children, handle);

}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
uint32 RBTransformComponent::GetChildrenCount() const
{
    return stb_arr_len(m_children);
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBTransformComponent::Update(RBTransformComponentHandle pComponent)
{
    RBTransformComponent& xForm = RBTransformComponent::Get(pComponent);
    RBTransformComponentHandle parentHandle = Parents[xForm.m_handle];

    xForm.WorldXForm() = (parentHandle != 0xFFFF) ? WorldXForms[parentHandle] * xForm.LocalXForm() : 
                                                    xForm.LocalXForm();

    RBTransformComponentHandle* children = xForm.m_children;
    uint32 children_count = stb_arr_len(children);
    for (uint32 child=0; child < children_count; ++child)
    {
        RBTransformComponentHandle childHandle = children[child];
        Update(childHandle);
    }

}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
void RBTransformComponent::UpdateEntity( RBEntityHandle handle )
{
    RBEntity& entity = RBEntity::Get(handle);
    uint16 xFormCount = entity.GetComponentCount<RBTransformComponent>();
    for (uint16  ui=0; ui < xFormCount; ++ui)
    {
        Update(entity.GetComponent<RBTransformComponent>(ui));
    }
}

